package com.zh.freechat.web;


import com.zh.webcommon.common.auth.annotation.NonePermission;
import com.zh.webcommon.common.viewdata.ApiResult;
import com.zh.webcommon.upload.FileKind;
import com.zh.webcommon.upload.FileUploadClient;
import com.zh.webcommon.upload.FileUploadResult;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Optional;
import java.util.function.BiFunction;

import static com.zh.mycommon.util.MyFileUtil.DATA_MB;
import static com.zh.webcommon.CommonConst.GSON;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * 文件上传下载 相关API
 * @author ZH
 * @date 15:29 2022/1/14
 */
@AllArgsConstructor
@Slf4j
@RestController
@RequestMapping("/file")
public class FileUploadController {
    private FileUploadClient fileUploadClient;
    /**
     * 图片文件上传
     *
     * @return
     */
    @PostMapping("/upload/picture")
    public ApiResult<String> fileUpload2(@RequestParam("file") MultipartFile file, @RequestParam(defaultValue = "") String flag) throws IOException {
        var filename = file.getOriginalFilename();
        var contentType = Optional.ofNullable(file.getContentType()).orElse("");
        var sizeM = file.getSize()/DATA_MB;
        log.debug("上传的图片文件信息：filename = {}, contentType = {}", filename, contentType);

        //验证文件格式是不是图片
        if (!contentType.startsWith("image/")) {
            throw new IllegalArgumentException("文件不是图片格式");
        }
        //文件过大，拒绝上传
        if (sizeM > 50) {
            throw new IllegalArgumentException("文件大小超出50M限制");
        }
        //图片size<1m时,压缩头像质量为1，逐级递减为0；size>20m时,压缩头像质量为0.6
        float quality = Math.max(1 - sizeM/20f,0.6f);

        //图片统一转为jpg格式
        var laterType = MediaType.IMAGE_JPEG;

        var outputStream = new ByteArrayOutputStream();
        //如果是头像，则压缩为size=512的头像图片
        if ("avatar".equals(flag)) {
            Thumbnails.of(file.getInputStream())
                    .crop(Positions.CENTER)
                    .size(512, 512)
                    .outputQuality(quality)
                    .outputFormat(laterType.getSubtype())
                    .toOutputStream(outputStream);
        }
        //如果不明确要原图，就压缩
        else if ("original".equals(flag)){
            Thumbnails.of(file.getInputStream())
                    .scale(1)
                    .outputQuality(1)
                    .outputFormat(laterType.getSubtype())
                    .toOutputStream(outputStream);
        } else {
            Thumbnails.of(file.getInputStream())
                    .scale(1)
                    .outputQuality(quality)
                    .outputFormat(laterType.getSubtype())
                    .toOutputStream(outputStream);
        }

        FileUploadResult result = fileUploadClient.upload(outputStream.toByteArray(), filename, MediaType.IMAGE_JPEG.toString());
        if (result.isOk()) {
            log.debug("图片文件[filename = {}]上传完成", filename);
            return ApiResult.success(result.getUrl());
        } else {
            log.warn("图片文件[filename = {}]上传失败.{}", filename,result.getError());
            return ApiResult.fail(result.getError());
        }
    }

    /**
     * 文件上传 MultipartFile
     */
    @NonePermission
    @PostMapping("/upload")
    public ApiResult<String> fileUpload(@RequestParam("file") MultipartFile file) {
        FileUploadResult uploadResult = fileUploadClient.upload(file);
        log.info("文件上传结果：{}", GSON.toJson(uploadResult));
        if (uploadResult.isOk()) {
            return ApiResult.success(uploadResult.getUrl());
        } else {
            return ApiResult.fail(uploadResult.getError());
        }
    }

    /**
     * 文件下载
     */
    @NonePermission
    @GetMapping("/download/{fileId}")
    public void fileDownload(@PathVariable("fileId") String filename, @RequestParam String etag, @RequestParam(required = false) String type
            , HttpServletResponse httpResponse) {
        httpResponse.setHeader("Content-Disposition", String.format("attachment;filename=%s", URLEncoder.encode(filename, UTF_8)));

        try {
            final ServletOutputStream outputStream = httpResponse.getOutputStream();
            BiFunction<Long, String, OutputStream> function = (Long size, String contentType) -> {
                httpResponse.setContentLengthLong(size);
                httpResponse.setContentType(contentType);
                return outputStream;
            };

            if (StringUtils.hasText(type)) {
                fileUploadClient.download(FileKind.valueOfAlias(type.trim()), filename, etag, function);
            } else {
                fileUploadClient.download(filename, etag, function);
            }
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }

}
